package com.ng.sys.service.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.ng.common.enums.MenuTypeEnum;
import com.ng.sys.model.domain.*;
import com.ng.sys.model.dto.Meta;
import com.ng.sys.model.response.RouteResponse;
import com.ng.sys.service.IMenu;
import cn.hutool.core.collection.CollectionUtil;

@Service
public class MenuImpl implements IMenu {

	@Override
	public List<Menu> list(String keywords) {

		String _sql = "select * from " + Menu.TABLE_NAME + " where 1=1 ";

		if (!StrKit.isBlank(keywords)) {
			_sql += " and name like '%" + keywords + "%' ";
		}
		_sql += " order by sort asc";

		List<Menu> menus = Menu.dao.find(_sql);

		Set<String> parentIds = menus.stream().map(Menu::getParentId).collect(Collectors.toSet());

		Set<String> menuIds = menus.stream().map(Menu::getId).collect(Collectors.toSet());

		List<String> rootIds = CollectionUtil.subtractToList(parentIds, menuIds); // 求差集，得到 parentIds 中 menuIds 没有的元素

		List<Menu> list = new ArrayList<Menu>();
		for (String rootId : rootIds) {
			list.addAll(recurMenus(rootId, menus)); // 递归
		}

		return list;
	}

	/**
	 * 递归生成菜单列表
	 *
	 * @param parentId 父级ID
	 * @param menuList 菜单列表
	 * @return
	 */
	private List<Menu> recurMenus(String parentId, List<Menu> menuList) {
		return CollectionUtil.emptyIfNull(menuList).stream().filter(menu -> menu.getParentId().equals(parentId))
				.map(entity -> {
					List<Menu> children = recurMenus(entity.getId(), menuList);
					entity.setChildren(children);
					return entity;
				}).collect(Collectors.toList());
	}

	@Override
	public List<RouteResponse> routes(String userId,String flag) {
		List<Menu> menus = Menu.dao.find(
				"select * from " + Menu.TABLE_NAME + " where type!=? and use_type=? and id in ( select menu_id from " + RoleMenu.TABLE_NAME
						+ " where role_id in (select role_id from " + UserRole.TABLE_NAME + " where user_id=? ) ) order by sort asc ",
						MenuTypeEnum.BUTTON.getType(),flag,userId);
		return recurRoutes("-1", menus);
	}
	
	private List<RouteResponse> recurRoutes(String parentId, List<Menu> menuList) {
		return CollectionUtil.emptyIfNull(menuList).stream().filter(menu -> menu.getParentId().equals(parentId))
				.map(menu -> {
					RouteResponse routeResponse = new RouteResponse();
					
					//类型(CATALOG-目录 MENU-菜单 BUTTON-按钮 EXTLINK-外链)
					
					if(StrKit.equals(MenuTypeEnum.CATALOG.getType(),menu.getType())) {
						routeResponse.setName(menu.getName());
						routeResponse.setPath(menu.getPath());
						routeResponse.setComponent(menu.getComponent());
						routeResponse.setRedirect(menu.getRedirect());
						Meta meta=new Meta();
						meta.setTitle(menu.getName());
						meta.setIcon(menu.getIcon());
						if(StrKit.equals("1", menu.getVisible())) {
							meta.setHidden(false);
						}else {
							meta.setHidden(true);
						}
						if(StrKit.equals("1", menu.getAlwaysShow())) {
							meta.setAlwaysShow(true);
						}else {
							meta.setAlwaysShow(false);
						}
						routeResponse.setMeta(meta);
						List<RouteResponse> children = recurRoutes(menu.getId(), menuList);
						routeResponse.setChildren(children);
					}
					else if(StrKit.equals(MenuTypeEnum.MENU.getType(),menu.getType())) {
						routeResponse.setName(menu.getRouteName());
						routeResponse.setComponent(menu.getComponent());
						routeResponse.setPath(menu.getPath());
						Meta meta=new Meta();
						meta.setTitle(menu.getName());
						meta.setIcon(menu.getIcon());
						if(StrKit.equals("1", menu.getVisible())) {
							meta.setHidden(false);
						}else {
							meta.setHidden(true);
						}
						if(StrKit.equals("1", menu.getAlwaysShow())) {
							meta.setAlwaysShow(true);
						}else {
							meta.setAlwaysShow(false);
						}
						if(StrKit.equals("1", menu.getKeepAlive())) {
							meta.setKeepAlive(true);
						}else {
							meta.setKeepAlive(false);
						}
						
						if(!StrKit.isBlank(menu.getParams())) {
							meta.setParams(JSONArray.parseArray(menu.getParams()));
						}
						
						routeResponse.setMeta(meta);
						List<RouteResponse> children = recurRoutes(menu.getId(), menuList);
						routeResponse.setChildren(children);
					}
					else if(StrKit.equals(MenuTypeEnum.EXTLINK.getType(),menu.getType())) {
						routeResponse.setName(menu.getName());
						routeResponse.setPath(menu.getPath());
						
						Meta meta=new Meta();
						meta.setTitle(menu.getName());
						meta.setIcon(menu.getIcon());
						if(StrKit.equals("1", menu.getVisible())) {
							meta.setHidden(false);
						}else {
							meta.setHidden(true);
						}
						if(StrKit.equals("1", menu.getAlwaysShow())) {
							meta.setAlwaysShow(true);
						}else {
							meta.setAlwaysShow(false);
						}
						
						if(!StrKit.isBlank(menu.getParams())) {
							meta.setParams(JSONObject.parseObject(menu.getParams()));
						}
						routeResponse.setMeta(meta);
						List<RouteResponse> children = recurRoutes(menu.getId(), menuList);
						routeResponse.setChildren(children);
					}
					return routeResponse;
				}).collect(Collectors.toList());
	}
	
	
	 /**
     * 菜单下拉数据
     */
	@Override
    public List<Menu> listMenuOptions() {
        return Menu.dao.find("select * from "+Menu.TABLE_NAME+" order by sort asc");
    }
    

	@Override
	public boolean delete(String id) {
		deleteChildrens(id);
		Db.delete("delete from "+RoleMenu.TABLE_NAME+" where menu_id=?",id);
		Db.delete("delete from "+Menu.TABLE_NAME+" where id=?",id);
        return true;
	}
	
	private void deleteChildrens(String id) {
		List<Menu> menus=Menu.dao.find("select id from "+Menu.TABLE_NAME+" where parent_id=?",id);
		for(Menu menu:menus) {
			deleteChildrens(menu.getId());
			Db.delete("delete from "+RoleMenu.TABLE_NAME+" where menu_id=?",menu.getId());
			menu.delete();
		}
	}

}
